home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / printing / rlpr-1.000 / rlpr-1 / rlpr-1.13 / rlpr-net.c < prev    next >
C/C++ Source or Header  |  1996-06-30  |  8KB  |  223 lines

  1. /* filename: rlpr-net.c
  2.  * project: rlpr
  3.  * author: meem  --  meem@sherilyn.wustl.edu
  4.  * version: $Id: rlpr-net.c,v 1.11 1996/07/01 01:11:33 meem Exp $
  5.  * contents: network-related parts of rlpr (all the socket-based functions)
  6.  *
  7.  * Time-stamp: <1996/06/30 20:35 -- meem@sherilyn>
  8.  */
  9.  
  10. /* copyright (c) 1996 meem, meem@gnu.ai.mit.edu
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 1, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20.  * General Public License for more details.
  21.  */
  22.  
  23. #include <sys/types.h>  
  24. #include <netinet/in.h>                 /* struct socketaddr_in definition */
  25. #include <sys/socket.h>                 /* all the different socket types */
  26. #include <sys/stat.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <netdb.h>                      /* network-specific functions here */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <sys/time.h>                   /* for timeval in select() calls */
  33. #include <unistd.h>                     /* for unlink(), etc */
  34. #include <errno.h>
  35. #include "rlpr-common.h"
  36. #include "rlpr-net.h"
  37.  
  38. void open_connection(void) {
  39.   struct sockaddr_in sin;               /* socket struct with system info */
  40.   struct sockaddr_in sin_local;       /* to bind a socket to a number */
  41.   struct hostent *hp;                   /* ptr to struct given by gethostbyname() */
  42.   int i, on;                        /* scrap variables */
  43.  
  44.   /* zero out structs to get the unused part zeroed */
  45.   memset(&sin,  0, sizeof(sin));
  46.   memset(&sin_local, 0, sizeof(sin_local));
  47.   
  48.   /* obtain a socket descriptor */
  49.   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* 0 == auto proto config */
  50.     rlpr_fatal("socket: %s", ERRNO);
  51.  
  52.   /* here if we're setuid root we can just bind to the right port
  53.      immediately and be done with it. otherwise we need to use a
  54.      proxy. if the proxy variable isn't set we assume they have it
  55.      installed setuid root. */
  56.  
  57.   if (!*opts_.proxyhost) {
  58.     if (!(hp = gethostbyname(local_hostname)))
  59.       rlpr_fatal("hostname \"%s\" does not seem to exist!", local_hostname);
  60.  
  61.     sin_local.sin_family = AF_INET;
  62.  
  63.     memcpy(&sin_local.sin_addr, hp->h_addr, hp->h_length);
  64.     
  65.     for (i = LO_LPD_FROM_NUM; i <= HI_LPD_FROM_NUM; i++) {
  66.       sin_local.sin_port = htons(i);
  67.       if (bind(sockfd, (struct sockaddr *) &sin_local, sizeof(sin_local)) >= 0)
  68.     break;
  69.     }
  70.  
  71.     if (i > HI_LPD_FROM_NUM)    /* didn't get a port */
  72.       if (errno == EACCES)
  73.     rlpr_fatal("bind to privileged port failed: "
  74.            "read rlpr(1) on using a proxyhost");
  75.       else rlpr_fatal("bind to ports %i-%i: %s", 
  76.               LO_LPD_FROM_NUM, HI_LPD_FROM_NUM, ERRNO);
  77.   }
  78.  
  79.   /* either we're connecting to the proxy or the real host */
  80.  
  81.   if (!*opts_.proxyhost) /* USE PRINTHOST */ {
  82.  
  83.     if (!(hp = gethostbyname(opts_.printhost)))
  84.       rlpr_fatal("hostname \"%s\" does not seem to exist!", opts_.printhost);
  85.     sin.sin_port = htons(LPD_TO_NUM);   /* put it in network byte order */
  86.         
  87.   } else /* USE PROXY */ {
  88.  
  89.     if (!(hp = gethostbyname(opts_.proxyhost)))
  90.       rlpr_fatal("hostname \"%s\" does not seem to exist!", opts_.proxyhost);
  91.     sin.sin_port = htons(RLPRD_TO_NUM);   /* put it in network byte order */
  92.   }
  93.  
  94.   /* fill in sin struct, and connect  */
  95.   memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); /* already in nbo */
  96.   sin.sin_family = AF_INET;
  97.  
  98.   if (connect(sockfd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
  99.     if (errno == ECONNREFUSED)
  100.       rlpr_fatal("connection to %s refused! are you sure the daemon is up?",
  101.          (*opts_.proxyhost) ? opts_.proxyhost : opts_.printhost);
  102.     else rlpr_fatal("connect: %s", ERRNO);
  103.  
  104.   if (*opts_.proxyhost) {    /* if proxy, send out final destination */
  105.     if (write(sockfd, opts_.printhost, strlen(opts_.printhost)) < 0)
  106.       rlpr_fatal("write to rlprd: %s", ERRNO);
  107.     if (write(sockfd, "\n", 1) < 0)
  108.       rlpr_fatal("newline write to rlprd: %s", ERRNO);
  109.   }
  110. }
  111.  
  112. void close_connection(void) {
  113.   if (close(sockfd) < 0)
  114.     rlpr_fatal("close: %s", ERRNO);
  115. }
  116.  
  117. void recv_job_req(void) {
  118.   char buf[BUFSIZ];             /* should be more precise here */
  119.  
  120.   sprintf(buf, "%c%s\n", RECVJ, opts_.printer);
  121.   if (write(sockfd, buf, strlen(buf)) < 0)
  122.     rlpr_fatal("write in recv_job_req: %s", ERRNO);
  123.   
  124.   if (read(sockfd, buf, 1) < 0) /* check acknolwedgement */
  125.     rlpr_fatal("read in recv_job_req: %s", ERRNO);
  126.   else if (*buf)
  127.     rlpr_fatal("unable to queue job: maybe printer is down or doesn't exist");
  128. }
  129.  
  130. void send_cf(int cfd, char *cfname) {
  131.   char buf[BUFSIZ];
  132.   int count;
  133.   char ack[1];                  /* acknowledgement byte */
  134.  
  135.   if (lseek(cfd, 0, SEEK_SET) < 0)
  136.     rlpr_fatal("lseek on control file: %s", ERRNO);
  137.  
  138.   sprintf(buf, "%c%lu %s\n", RECVCF, filesz(cfd), cfname);
  139.   if (write(sockfd, buf, strlen(buf)) < 0)
  140.     rlpr_fatal("write in send_cf: %s", ERRNO);
  141.  
  142.   if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
  143.     rlpr_fatal("read in send_cf: %s", ERRNO);
  144.   if (*ack) rlpr_fatal("server did not acknowledge client in send_cf");
  145.   
  146.   while ((count = read(cfd, buf, BUFSIZ)) > 0) {
  147.     if (write(sockfd, buf, count) < 0)
  148.       rlpr_fatal("in sending control file to client: %s", ERRNO);
  149.   }
  150.   if (!count) {
  151.     if (write(sockfd, "\0", 1) < 0)
  152.       rlpr_fatal("write of acknowledgement in send_cf: %s", ERRNO);
  153.   }
  154.   else if (count < 0) rlpr_fatal("read on control file: %s", ERRNO);
  155.  
  156.   if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
  157.     rlpr_fatal("read in send_cf: %s", ERRNO);
  158.   if (*ack) rlpr_fatal("server did not acknowledge client in send_cf");
  159. }
  160.  
  161.  
  162. void send_df(char *filename, char *dfname) {
  163.   char buf[BUFSIZ];        /* temporary buffer */
  164.   int count;
  165.   char ack[1];                  /* acknowledgement byte */
  166.   int dfd;            /* descriptor for datafile */
  167.   
  168.   if (!filename) /* STDIN */ {
  169.  
  170.     /* we need to make a dummy file to send, so that we know the size
  171.      * of stdin for machines that are not local. this is annoying but
  172.      * apparently required for most lpd's (even though RFC 1179 seems
  173.      * to say otherwise)
  174.      */
  175.  
  176.     filename = malloc(strlen(dfname) + strlen(TMPDIR) + 1);
  177.     sprintf(filename, "%s%s", TMPDIR, dfname);
  178.  
  179.     if ((dfd = open(filename, O_RDWR|O_TRUNC|O_CREAT)) < 0)
  180.       rlpr_fatal("open on temporary file %s: %s",filename, ERRNO);
  181.     unlink(filename);
  182.  
  183.     while ((count = read(STDIN_FILENO, buf, BUFSIZ)) > 0)
  184.       if (write(dfd, buf, count) < 0)
  185.     rlpr_fatal("writing stdin to temporary file %s: %s",
  186.            filename, ERRNO);
  187.       else if (count < 0)
  188.     rlpr_fatal("read on stdin: %s", ERRNO);      
  189.  
  190.     lseek(dfd, 0, SEEK_SET);
  191.     
  192.     /* else have a filename from the commandline */
  193.  
  194.   } else if ((dfd = open(filename, O_RDONLY)) < 0)
  195.     rlpr_fatal("cannot open %s: %s", filename, ERRNO);
  196.  
  197.   /* COMMON */
  198.  
  199.   sprintf(buf, "%c%lu %s\n", RECVDF, filesz(dfd), dfname);
  200.   
  201.   if (write(sockfd, buf, strlen(buf)) < 0)
  202.     rlpr_fatal("write in send_df: %s", ERRNO);
  203.   
  204.   if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
  205.     rlpr_fatal("read in send_df: %s", ERRNO);
  206.   if (*ack) rlpr_fatal("server did not acknowledge client in send_df1");
  207.   
  208.   while ((count = read(dfd, buf, BUFSIZ)) > 0) {
  209.     if (write(sockfd, buf, count) < 0)
  210.       rlpr_fatal("in sending %s to client: %s",
  211.          filename ? filename : "stdin", ERRNO);
  212.   }
  213.   if (!count) {
  214.     if (write(sockfd, "\0", 1) < 0)
  215.       rlpr_fatal("write of acknowledgement in send_df: %s", ERRNO);
  216.   }
  217.   else if (count < 0) rlpr_fatal("read on data file: %s", ERRNO);
  218.    
  219.   if (read(sockfd, ack, 1) < 0) /* check acknolwedgement */
  220.     rlpr_fatal("read in send_df: %s", ERRNO);
  221.   if (*ack) rlpr_fatal("server did not acknowledge client in send_df2");
  222. }
  223.